-
Notifications
You must be signed in to change notification settings - Fork 144
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add ML-KEM (FIPS 203). #470
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lots of nits, the only really "wrong" thing is a documentation comment.
LGTM otherwise!
@@ -143,6 +151,9 @@ func (pk *PublicKey) EncapsulateTo(ct, ss []byte, seed []byte) { | |||
// c = Kyber.CPAPKE.Enc(pk, m, r) | |||
pk.pk.EncryptTo(ct, m[:], kr[32:]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While at it, maybe we can use a name for this constant. This matches the type of K
in the Algorithm 16 from FIPS 203 ("derive shared secret K and randomness r") and is consistent with your other use of kr[:SharedKeySize]
below.
pk.pk.EncryptTo(ct, m[:], kr[32:]) | |
pk.pk.EncryptTo(ct, m[:], kr[SharedKeySize:]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is accidental, and that 32 is not the shared key size.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not following.
My understanding is that the first part of kr
is the shared secret key. So kr[SharedKeySize:]
would skip the shared secret key, and refer to the remaining part, r
.
Output: shared key K ∈ B32
(K, r) ← G(m ∥ H(ek)) ▷ derive shared secret key K and randomness r
c ← K-PKE.Encrypt(ek, m, r) ▷ encrypt m using K-PKE with randomness r
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In Kyber the first 32 bytes does not contain the returned shared secret, but an intermediate key that happens to be 32 bytes as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In that case, what about replacing kr[:SharedKeySize]
by kr[:32]
to avoid that implication?
Thanks. Addressed. |
Any updates on this? Is there something that prevents it from being merged? Our view is that the "draft" status will probably remain for some time to come. Hopefully we can see this merged before the draft label is removed. |
ML-KEM is not final and could well have a breaking change compared to the initial public draft which is implemented by this PR.
We expect the final version of ML-KEM this year, and that could be as early as this month. |
Thank you for those clarifications, and the quick reply. |
@@ -7,8 +7,10 @@ package main | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you please move these files used to generate code to an internal
folder.
/kem/internal/gen.go
/kem/internal/pkg.templ.go
Generated packages:
/kem/kyber*
/kem/mlkem*
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you please move these files used to generate code to an
internal
folder.
Shall we do that in a separate PR? It's not only Kyber that has a gen.go
outside of an internal
.
6d7c6f4
to
9095c87
Compare
kem/mlkem/acvp_test.go
Outdated
t.Fatal(err) | ||
} | ||
|
||
if dk.Equal(dk2) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Based on the error message, aren't these two conditions inverted?
if dk.Equal(dk2) { | |
if !dk.Equal(dk2) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oof. Well spotted. Let me figure out why it fails...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, apparently the ACVP test vectors haven't been updated yet.
// key is not normalized. | ||
func (pk *PublicKey) UnpackMLKEM(buf []byte) error { | ||
if len(buf) != PublicKeySize { | ||
return kem.ErrPubKeySize |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The previous Pack/Unpack
function panics instead of returning an error when the size does not match.
We keep Kyber around (for now) as it's currently widely deployed. Code differences between them are minimal anyway. Tests against NIST's ACVP test vectors.
Implementation of ML-KEM (FIPS 203).
We keep Kyber around (for now) as it's currently widely deployed. Code differences between them are minimal anyway.
Changes from IPD:
which still have to be updated to match FIPS203.are updated